package com.zatech.cgnci.project.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zatech.cgnci.project.base.enums.ResponseCodeEnum;
import com.zatech.cgnci.project.base.exception.GlobalException;
import com.zatech.cgnci.project.base.utils.BeanUtils;
import com.zatech.cgnci.project.base.utils.VerifyUtils;
import com.zatech.cgnci.project.entity.*;
import com.zatech.cgnci.project.mapper.CgnciReinsuranceRiskLayerMapper;
import com.zatech.cgnci.project.service.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 分入分出层表 服务实现类
 * </p>
 *
 * @author Generator
 * @since 2024-12-18
 */
@Service
public class CgnciReinsuranceRiskLayerServiceImpl extends ServiceImpl<CgnciReinsuranceRiskLayerMapper, CgnciReinsuranceRiskLayerDO> implements CgnciReinsuranceRiskLayerService {

    @Resource
    CgnciReinsuranceRiskService reinsuranceRiskService;
    @Resource
    CgnciReinsuranceInfoService reinsuranceInfoService;
    @Resource
    CgnciReinsurerService reinsurerService;
    @Resource
    CgnciReinsuranceRiskInsuredService reinsuranceRiskInsuredService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteLayer(Long layerId, String type) {
        CgnciReinsuranceRiskLayerDO layerDO = this.getById(layerId);
        if (VerifyUtils.isEmpty(layerDO)) {
            throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR, "layerId有误");
        }

        // 查询险种标的
        CgnciReinsuranceRiskInsuredDO insuredDO = reinsuranceRiskInsuredService.getById(layerDO.getReinsuranceRiskId());
        if (VerifyUtils.isEmpty(layerDO)) {
            throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR, "未找到险种标的信息");
        }

        // 查询险种对应的险种信息
        CgnciReinsuranceRiskDO reinsuranceRiskDO = reinsuranceRiskService.getById(insuredDO.getReinsuranceRiskId());
        if (VerifyUtils.isEmpty(reinsuranceRiskDO)) {
            throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR, "未找到险种信息");
        }

        switch (type) {
            case "1":
                // 查询险种对应的分入信息
                CgnciReinsuranceInfoDO divideInReinsuranceInfoDO = reinsuranceInfoService.getById(reinsuranceRiskDO.getReinsuranceId());
                if (VerifyUtils.isEmpty(divideInReinsuranceInfoDO)) {
                    return;
                }
                // 处理险种对应的分入信息汇总字段
                List<CgnciReinsuranceRiskInsuredDO> divideInReinsuranceRiskInsuredDOS = new ArrayList<>();
                divideInReinsuranceRiskInsuredDOS.add(insuredDO);
                reinsuranceInfoService.updateReinsuranceColumn(divideInReinsuranceRiskInsuredDOS, divideInReinsuranceInfoDO, layerDO.getLayerId());
                this.removeById(layerDO.getLayerId());

                // 当分人信息的分人方式为2-非比例，并且分出信息的分出价格确认为1-按分人净保费时，
                // 还必须处理临分分出信息该险种该标的对应的层字段（分出毛保费，分保手续费，分出净保费，再保经纪费）都得更新，并且重新计划汇总
                // 查询分出信息
                CgnciReinsuranceInfoDO divideOutReinsuranceInfoDO1 = reinsuranceInfoService.getOne(new LambdaQueryWrapper<>(CgnciReinsuranceInfoDO.class)
                        .eq(CgnciReinsuranceInfoDO::getBusinessId, divideInReinsuranceInfoDO.getBusinessId())
                        .eq(CgnciReinsuranceInfoDO::getReinsuranceType, "3"));
                if (VerifyUtils.isEmpty(divideOutReinsuranceInfoDO1)) {
                    return;
                }
                if ("2".equals(divideInReinsuranceInfoDO.getReinsuranceMethod()) && "1".equals(divideOutReinsuranceInfoDO1.getPriceConfirmationType())) {
                    // 根据分人险种和分出ID险种对应的险种信息
                    CgnciReinsuranceRiskDO divideOutReinsuranceRiskDO = reinsuranceRiskService.getOne(new LambdaQueryWrapper<>(CgnciReinsuranceRiskDO.class)
                            .eq(CgnciReinsuranceRiskDO::getReinsuranceId, divideOutReinsuranceInfoDO1.getReinsuranceId())
                            .eq(CgnciReinsuranceRiskDO::getRiskSubTypeCode, reinsuranceRiskDO.getRiskSubTypeCode()));
                    if (VerifyUtils.isEmpty(divideOutReinsuranceRiskDO)) {
                        return;
                    }

                    // 查询险种标的
                    CgnciReinsuranceRiskInsuredDO divideOutInsuredDO = reinsuranceRiskInsuredService.getOne(new LambdaQueryWrapper<>(CgnciReinsuranceRiskInsuredDO.class)
                            .eq(CgnciReinsuranceRiskInsuredDO::getReinsuranceRiskId, divideOutReinsuranceRiskDO.getReinsuranceRiskId())
                            .eq(CgnciReinsuranceRiskInsuredDO::getRowKey, insuredDO.getRowKey()));
                    if (VerifyUtils.isEmpty(divideOutInsuredDO)) {
                        return;
                    }

                    // 查询分人险种标的下的层
                    List<CgnciReinsuranceRiskLayerDO> divideInLayers = this.list(new LambdaQueryWrapper<>(CgnciReinsuranceRiskLayerDO.class)
                            .eq(CgnciReinsuranceRiskLayerDO::getReinsuranceRiskId, insuredDO.getRiskInsuredId()));
                    // 汇总该险种标的的分人净保费
                    BigDecimal divideInNetPremium = BeanUtils.sumBigDecimalProperty(divideInLayers, CgnciReinsuranceRiskLayerDO::getNetPremium);

                    // 查询分出层是否存在分入信息删除对应的的该险种该标的该层名称
                    List<CgnciReinsuranceRiskLayerDO> divideOutLayers = this.list(new LambdaQueryWrapper<>(CgnciReinsuranceRiskLayerDO.class)
                            .eq(CgnciReinsuranceRiskLayerDO::getReinsuranceRiskId, divideOutInsuredDO.getRiskInsuredId()));
                    if (VerifyUtils.isEmpty(divideOutLayers)) {
                        return;
                    }

                    // 分入/分出毛保费
                    BigDecimal sourceGrossPremium = BeanUtils.sumBigDecimalProperty(divideOutLayers, CgnciReinsuranceRiskLayerDO::getGrossPremium);
                    // 分入/分出手续费
                    BigDecimal sourceCommission = BeanUtils.sumBigDecimalProperty(divideOutLayers, CgnciReinsuranceRiskLayerDO::getCommission);
                    // 分入/分出净保费
                    BigDecimal sourceNetPremium = BeanUtils.sumBigDecimalProperty(divideOutLayers, CgnciReinsuranceRiskLayerDO::getNetPremium);
                    // 分入/分出再保经纪费
                    BigDecimal sourceBrokerFee = BeanUtils.sumBigDecimalProperty(divideOutLayers, CgnciReinsuranceRiskLayerDO::getBrokerFee);
                    // 更新分入/分出信息汇总字段
                    if (VerifyUtils.isNotEmpty(divideOutReinsuranceInfoDO1.getTotalGrossPremium())) {
                        divideOutReinsuranceInfoDO1.setTotalGrossPremium(divideOutReinsuranceInfoDO1.getTotalGrossPremium().subtract(sourceGrossPremium));
                    }
                    if (VerifyUtils.isNotEmpty(divideOutReinsuranceInfoDO1.getTotalCommission())) {
                        divideOutReinsuranceInfoDO1.setTotalCommission(divideOutReinsuranceInfoDO1.getTotalCommission().subtract(sourceCommission));
                    }
                    if (VerifyUtils.isNotEmpty(divideOutReinsuranceInfoDO1.getTotalNetPremium())) {
                        divideOutReinsuranceInfoDO1.setTotalNetPremium(divideOutReinsuranceInfoDO1.getTotalNetPremium().subtract(sourceNetPremium));
                    }
                    if (VerifyUtils.isNotEmpty(divideOutReinsuranceInfoDO1.getTotalBrokerFee())) {
                        divideOutReinsuranceInfoDO1.setTotalBrokerFee(divideOutReinsuranceInfoDO1.getTotalBrokerFee().subtract(sourceBrokerFee));
                    }

                    // 根据分人净保费基数重新计算分出的层字段
                    divideOutLayers.forEach(layer -> {
                        // 分出毛保费 = 分入净保费*层分出比例
                        layer.setGrossPremium(divideInNetPremium.multiply(VerifyUtils.isEmpty(layer.getCededRatio()) ? BigDecimal.ZERO : layer.getCededRatio()));
                        // 分保手续费 = 分出毛保费*分保手续费率
                        layer.setCommission(layer.getGrossPremium().multiply(VerifyUtils.isEmpty(divideOutReinsuranceInfoDO1.getTotalBrokerCommissionRate()) ? BigDecimal.ZERO : divideOutReinsuranceInfoDO1.getTotalBrokerCommissionRate()));
                        // 分出净保费 = 分出毛保费-分保手续费
                        layer.setNetPremium(layer.getGrossPremium().subtract(layer.getCommission()));
                        // 再保经纪费 = 分出毛保费*再保经纪费率
                        layer.setBrokerFee(layer.getGrossPremium().multiply(VerifyUtils.isEmpty(divideOutReinsuranceInfoDO1.getBrokerFeeRate()) ? BigDecimal.ZERO : divideOutReinsuranceInfoDO1.getBrokerFeeRate()));
                    });
                    this.updateBatchById(divideOutLayers);

                    // 分入/分出毛保费
                    BigDecimal grossPremium = BeanUtils.sumBigDecimalProperty(divideOutLayers, CgnciReinsuranceRiskLayerDO::getGrossPremium);
                    // 分入/分出手续费
                    BigDecimal commission = BeanUtils.sumBigDecimalProperty(divideOutLayers, CgnciReinsuranceRiskLayerDO::getCommission);
                    // 分入/分出净保费
                    BigDecimal netPremium = BeanUtils.sumBigDecimalProperty(divideOutLayers, CgnciReinsuranceRiskLayerDO::getNetPremium);
                    // 分入/分出再保经纪费
                    BigDecimal brokerFee = BeanUtils.sumBigDecimalProperty(divideOutLayers, CgnciReinsuranceRiskLayerDO::getBrokerFee);
                    // 更新分入/分出信息汇总字段
                    if (VerifyUtils.isNotEmpty(divideOutReinsuranceInfoDO1.getTotalGrossPremium())) {
                        divideOutReinsuranceInfoDO1.setTotalGrossPremium(divideOutReinsuranceInfoDO1.getTotalGrossPremium().add(grossPremium));
                    }
                    if (VerifyUtils.isNotEmpty(divideOutReinsuranceInfoDO1.getTotalCommission())) {
                        divideOutReinsuranceInfoDO1.setTotalCommission(divideOutReinsuranceInfoDO1.getTotalCommission().add(commission));
                    }
                    if (VerifyUtils.isNotEmpty(divideOutReinsuranceInfoDO1.getTotalNetPremium())) {
                        divideOutReinsuranceInfoDO1.setTotalNetPremium(divideOutReinsuranceInfoDO1.getTotalNetPremium().add(netPremium));
                    }
                    if (VerifyUtils.isNotEmpty(divideOutReinsuranceInfoDO1.getTotalBrokerFee())) {
                        divideOutReinsuranceInfoDO1.setTotalBrokerFee(divideOutReinsuranceInfoDO1.getTotalBrokerFee().add(brokerFee));
                    }
                    // 汇总分出字段汇总
                    reinsuranceInfoService.updateById(divideOutReinsuranceInfoDO1);
                }
                break;
            case "2":
                // 查询险种对应的分出信息
                CgnciReinsuranceInfoDO divideOutReinsuranceInfoDO2 = reinsuranceInfoService.getById(reinsuranceRiskDO.getReinsuranceId());
                if (VerifyUtils.isEmpty(divideOutReinsuranceInfoDO2)) {
                    return;
                }
                // 处理险种对应的分出信息汇总字段
                List<CgnciReinsuranceRiskInsuredDO> divideOutReinsuranceRiskInsuredDOS = new ArrayList<>();
                divideOutReinsuranceRiskInsuredDOS.add(insuredDO);
                reinsuranceInfoService.updateReinsuranceColumn(divideOutReinsuranceRiskInsuredDOS, divideOutReinsuranceInfoDO2, layerDO.getLayerId());

                // 删除分入分出层表数据
                this.removeById(layerId);
                break;
            case "3":
                // 查询险种对应的方案信息/再保人
                CgnciReinsurerDO reinsurerDO = reinsurerService.getById(reinsuranceRiskDO.getReinsuranceId());
                if (VerifyUtils.isEmpty(reinsurerDO)) {
                    return;
                }
                // 处理险种对应的方案信息/再保人汇总字段
                List<CgnciReinsuranceRiskInsuredDO> reinsurerRiskInsuredDOS = new ArrayList<>();
                reinsurerRiskInsuredDOS.add(insuredDO);
                reinsurerService.updateReinsurerColumn(reinsurerRiskInsuredDOS, reinsurerDO, layerDO.getLayerId());

                // 删除分入分出层表数据
                this.removeById(layerId);
                break;
            default:
                throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR, "type参数有误");
        }


    }
}
